﻿using Cofe.Core.Actions;
using Cofe.Core.Dynamic;
using Cofe.Core.Filter;
using Cofe.Core.Implements;
using Cofe.Core.Interfaces;
using Cofe.Core.Logger;
using Cofe.Core.Property;
using Cofe.Core.Security;
using Cofe.Core.Service;
using Cofe.Core.Session;
using Cofe.Core.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core.EntryType;
using Cofe.Core.Tasks;
using Cofe.Core.Entry;
using Cofe.Web;
using Cofe.Core.Script;

namespace Cofe.Core
{
    public static class CofeServices
    {
        #region Constructor

        static CofeServices()
        {
            
            //ServiceLocater = new ServiceLocater();
        }

        #endregion

        #region Methods

        public static void RegisterBaseServices(this ManualServiceImporter msi)
        {
            msi.RegisterService(
#if NETFX_CORE
                new DebugLogger(),
#else
new ConsoleLogger(),
#endif
 new CofeSettings(),
                new SecurityManager(),
                new CofeDynamicInterfaceManager(),
                new MemoryPropertyCache.Factory(),
                new PropertyCacheUpdater(), new PropertyBehaviorManager.Factory(),
                new GetFirst(), new GetAggregated(), new GetFirstHandled(), new GetMinMax(), new GetCacheOnly(),
                new SetFirst(), new SetAggregated(), new SetFirstHandled(), new SetCacheOnly(),
                new SecurityManager(), new UserManager(),
                //new CombineFirst(), new CombineAggregate(), new CombineFirstHandled(),
                new ListAllSupported());
        }

        public static void ImportServices(params ICofeService[] services)
        {
            var msi = new ManualServiceImporter(services);
            msi.RegisterBaseServices();
            ImportServices(msi);
        }

        public static void ImportServices(IServiceImporter importer)
        {
            ServiceLocater = new ServiceLocater();
            var services = importer.ImportServices();
            ServiceLocater.Register(services);

            notifyImported();

            CofeServices.Logger.Log(String.Format("CS: Imported {0} Services", services.Count()));
            _serviceImported = true;
            //EventHub.DispatchEvent<EventArgs>(null, EventArgs.Empty);
        }

        public static Task RestoreAsync()
        {
            return Task.Run(() =>
                {
                    CofeSettings.RestoreAsync().Wait();
                    Task.WaitAll(
                        (from s in ServiceLocater.FindAllServices<ISaveSettings>()
                         select Task.Run(async () => await s.RestoreAsync(CofeSettings))).ToArray());
                });

        }

        public static Task SaveAsync()
        {
            return Task.Run(() =>
            {
                Task.WaitAll(
                    (from s in ServiceLocater.FindAllServices<ISaveSettings>()
                     select Task.Run(async () => await s.SaveAsync(CofeSettings))).ToArray());
                CofeSettings.SaveAsync().Wait();
            });

        }

        public static void resetProperties()
        {
            _logger = null;
            _cofeSettings = null;
            _interfaceManager = null;
            _securityManager = null;
            _userManager = null;
            _propertyDictionary = null;
            _entryConstructor = null;
            _volumeRegistrar = null;
            _entryFilterParser = null;
            _paramParser = null;
            _pathParserManager = null;
            _eventHub = null;
            _transferManager = null;
            _etim = null;
            _pcf = null;
            _tm = null;
            _elr = null;
            _exs = null;
            _ejs = null;
            _ss = null;
        }

        private static void notifyImported()
        {
            _serviceImported = true;
            foreach (var s in ServiceLocater.FindAllServices<INotifyImported>())
                s.OnImported(ServiceLocater);
        }

        #endregion

        #region Data

        private static IServiceLocater _serviceLocater = null;

        private static bool _serviceImported = false;
        private static ILogger _logger = null;
        private static ICofeSettings _cofeSettings = null;
        private static IDynamicPropertyInterfaceManager _interfaceManager = null;
        private static ISecurityManager _securityManager = null;
        private static IUserManager _userManager = null;
        private static IPropertyDictionary _propertyDictionary = null;
        private static IEntryConstructor _entryConstructor = null;
        private static IVolumeRegistrar _volumeRegistrar = null;
        private static IEntryOptionFilterParser _entryFilterParser = null;
        private static IParamParser _paramParser = null;
        private static IPathParserManager _pathParserManager = null;
        private static IEventHub _eventHub = null;
        private static ITransferManager _transferManager = null;
        private static IEntryTypeInfoManager _etim = null;
        private static IPropertyCacheFactory _pcf = null;
        private static ITaskManager _tm = null;
        private static IEntryListRegistrar _elr = null;
        private static IEntryXmlSerializer _exs = null;
        private static IEntryJObjectSerializer _ejs = null;
        private static IScriptServices _ss = null;

        #endregion

        #region Public Properties

        public static bool ServiceImported { get { return _serviceImported; } }
        public static IServiceLocater ServiceLocater { get { return _serviceLocater; } 
            set { resetProperties(); _serviceLocater = value; notifyImported(); } }

        public static ILogger Logger
        {
            get
            {
                if (_logger != null)
                    return _logger;
                else
                {
                    _logger = CofeServices.ServiceLocater.TryFindService<ILogger>();
                    if (_logger == null)
                        return new DummyLogger();
                    return _logger;
                }

            }
        }
        public static ICofeSettings CofeSettings { get { return _cofeSettings ?? (_cofeSettings = CofeServices.ServiceLocater.FindService<ICofeSettings>()); } }
        public static IDynamicPropertyInterfaceManager PropertyInterfaceManager { get { return _interfaceManager ?? (_interfaceManager = CofeServices.ServiceLocater.FindService<IDynamicPropertyInterfaceManager>()); } }
        public static ISecurityManager SecurityManager { get { return _securityManager ?? (_securityManager = CofeServices.ServiceLocater.FindService<ISecurityManager>()); } }
        public static IUserManager UserManager { get { return _userManager ?? (_userManager = CofeServices.ServiceLocater.FindService<IUserManager>()); } }
        public static IPropertyDictionary PropertyDictionary { get { return _propertyDictionary ?? (_propertyDictionary = CofeServices.ServiceLocater.FindService<IPropertyDictionary>()); } }
        public static IEntryConstructor EntryConstructor { get { return _entryConstructor ?? (_entryConstructor = CofeServices.ServiceLocater.FindService<IEntryConstructor>()); } }
        public static IVolumeRegistrar VolumeRegistrar { get { return _volumeRegistrar ?? (_volumeRegistrar = CofeServices.ServiceLocater.FindService<IVolumeRegistrar>()); } }
        public static IEntryOptionFilterParser EntryFilterParser { get { return _entryFilterParser ?? (_entryFilterParser = CofeServices.ServiceLocater.FindService<IEntryOptionFilterParser>()); } }
        public static IParamParser ParamParser { get { return _paramParser ?? (_paramParser = CofeServices.ServiceLocater.FindService<IParamParser>()); } }
        public static IPathParserManager PathParserManager { get { return _pathParserManager ?? (_pathParserManager = CofeServices.ServiceLocater.FindService<IPathParserManager>()); } }
        public static IEventHub EventHub { get { return _eventHub ?? (_eventHub = CofeServices.ServiceLocater.FindService<IEventHub>()); } }
        public static ITransferManager TransferManager { get { return _transferManager ?? (_transferManager = CofeServices.ServiceLocater.FindService<ITransferManager>()); } }
        public static IPropertyCacheFactory PropertyCacheFactory { get { return _pcf ?? (_pcf = ServiceLocater.FindService<IPropertyCacheFactory>()); } }
        public static IEntryTypeInfoManager EntryTypeInfoManager { get { return _etim ?? (_etim = ServiceLocater.FindService<IEntryTypeInfoManager>()); } }
        public static ITaskManager TaskManager { get { return _tm ?? (_tm = ServiceLocater.FindService<ITaskManager>()); } }
        public static IEntryListRegistrar EntryListRegistrar { get { return _elr ?? (_elr = ServiceLocater.FindService<IEntryListRegistrar>()); } }
        public static IEntryXmlSerializer EntryXmlSerializer { get { return _exs ?? (_exs = ServiceLocater.FindService<IEntryXmlSerializer>()); } }
        public static IEntryJObjectSerializer EntrySerializer { get { return _ejs ?? (_ejs = ServiceLocater.FindService<IEntryJObjectSerializer>()); } }
        public static IScriptServices Script { get { return _ss ?? (_ss = ServiceLocater.FindService<IScriptServices>()); } }

        #endregion
    }
}
